項目51 不必要な型パラメーターを避ける
ジェネリックの黄金律
型パラメータは2回登場すべきである
型パラメータは複数の値の型を関連付けるためのもの
型パラメータが型シグネチャで一度しか使用されない場合、それは何も関連付けていない状態
ルール
型パラメータが一箇所にしか登場しない場合、それが本当に必要かどうか考え直す
良いジェネリックの使い方
⭕️
型パラメータT が宣言された後、2回登場している
入力パラメータの型と戻り値の型が同じということで関連付けられている
この関数は、コールバックを渡す必要があるが、データを変更したくない場合に有効
code:ts
function identity<T>(arg: T): T {
// (宣言) 1 2
return arg;
}
const date = identity(new Date());
// ^? const date: Date
// ^? const nums: number[]
❌️
2回以上登場しないパラメータが存在している
code:ts
function third<A, B, C>(a: A, b: B, c: C): C {
return c;
}
上記のジェネリックは下記の置き換えることができる
code:ts
function third<C>(a: unknown, b: unknown, c: C): C {
return c;
}
❌️
戻り値方のみのジェネリック
code:ts
declare function parseYAML<T>(input: string): T;
解決策
戻り値の型にunknown型を使って、利用する側に型アサーションの利用を強制させる
code:ts
declare function parseYAML(input: string): unknown;
const w = parseYAML('') as Weight;
❌️
一度しか登場しないパラメータKが存在している
code:ts
function printProperty<T, K extends keyof T>(obj: T, key: K) {
}
解決方法
keyof Tをパラメータ型に移動し、Kをなくす
code:ts
function printProperty<T>(obj: T, key: keyof T) {
}
⭕️
一度しか登場しないパラメータでも、型推論によって2度登場している
code:ts
function getProperty<T, K extends keyof T>(obj: T, key: K) {
}
上記のコードは下記のコードと等価
code:ts
function getProperty<T, K extends keyof T>(obj: T, key: K): TK { }